#pragma once
#include <chrono>
#include <iostream>

using sysclock = std::chrono::system_clock;
using time_point = sysclock::time_point;
using sysdur = time_point::duration;

template <typename P, typename R = void>
auto durcast(const sysdur& from, const std::chrono::duration<P, R>&)
    -> std::chrono::duration<P, R>
{
    using namespace std::chrono;
    return duration_cast<duration<P, R>>(from);
}

template <size_t N>
class ScopedTimer
{
  public:
    using clock = std::chrono::steady_clock;

    explicit ScopedTimer(char const (&func)[N])
        : func_(func), start_{clock::now()}
    {
    }

    ScopedTimer(const ScopedTimer&) = delete;
    ScopedTimer(ScopedTimer&&) = delete;
    ScopedTimer& operator=(const ScopedTimer&) = delete;
    ScopedTimer& operator=(ScopedTimer&&) = delete;

    ~ScopedTimer()
    {
        using namespace std::chrono;
        auto stop = clock::now();
        auto duration = (stop - start_);
        auto ms = duration_cast<milliseconds>(duration).count();
        std::cout << ms << " ms " << func_ << '\n';
    }

  private:
    const char (&func_)[N];
    const clock::time_point start_{};
};
